package schedule;

import java.util.ArrayList;

import plan.Plan;
import auftrag.Auftrag;
import auftrag.Ressource;

public class IterateOrdersThreshold implements ISchedule {
	long lMaxTime = 60000;
	double t = 500;
	int mMethod = 0;
	
	public Plan makePlan(ArrayList<?> pAuftragList,
			ArrayList<Ressource> pRessourceList, int pMethod) {
		mMethod = pMethod;
		return makePlan(pAuftragList, pRessourceList);
	}
	
	@Override
	public Plan makePlan(ArrayList<?> pAuftragList,
			ArrayList<Ressource> pRessourceList) {
		Plan p = new Plan();
		ArrayList<Auftrag> arrSortAuftrag = new ArrayList<Auftrag>();
		for(Object o : pAuftragList){
			if(Auftrag.class.isInstance(o)){
				arrSortAuftrag.add((Auftrag)o);
			}
		}
		//Initial-Plan nach EDF
		p = new SimplePlan().makePlan(arrSortAuftrag, pRessourceList);
		int nCountNothingChanged = 0;
		int quality = p.getQuality(true);
		t = Math.min(quality / 20, 500);
		long lStart = System.currentTimeMillis();
		long timeIteration = 0;
		while(System.currentTimeMillis()-lStart < lMaxTime-timeIteration && p.getQuality(false) > 0){
			timeIteration = System.currentTimeMillis();
			Plan pNeighbour;
			quality = p.getQuality(true);
			
			Auftrag a1=null, a2=null;
			int n1=0,n2=0;
			boolean swapped = false;
			for(int i = 1; i < arrSortAuftrag.size(); i++){
				a1 = arrSortAuftrag.get(i);
				int prob1 = (int)(Math.random()*20);
				if(a1.getEndDate() > a1.getDeadline() && prob1 < 1){
					for(int j = i-1; j>=0;j--){
						a2 = arrSortAuftrag.get(j);
						int prob2 = (int)(Math.random()*5);
						if(a2.getEndDate() < a2.getDeadline() && prob2 < 1){
							n1 = i;
							n2 = j;
							arrSortAuftrag.remove(a1);
							arrSortAuftrag.add(n2, a1);
							swapped = true;
							break;
						}
					}
					if(swapped)
						break;
				}
			}
			
			if(swapped){
				for(Ressource r : pRessourceList)
					r.clear();
			
				pNeighbour = new SimplePlan().makePlan(arrSortAuftrag, pRessourceList, mMethod);
			
				//falls Plan besser, behalten
				if(pNeighbour.getQuality(true) < quality + t){
					p = pNeighbour;
					nCountNothingChanged = 0;			
					//sonst: Rollback, t verkleinern
				} else {
					arrSortAuftrag.remove(a1);
					arrSortAuftrag.add(n1, a1);
				
					for(Ressource r : pRessourceList)
						r.clear();
				
					p = new SimplePlan().makePlan(arrSortAuftrag, pRessourceList, mMethod);
					if(nCountNothingChanged > 0 && nCountNothingChanged % 3 == 0){
						t=t*0.9;
					}
				}
			}
			timeIteration = System.currentTimeMillis()-timeIteration;
		}
		for(Ressource r : pRessourceList)
			r.clear();
		p = new SimplePlan().makePlan(arrSortAuftrag, pRessourceList, mMethod);
		return p;
	}
	
	public void setMaxTime(long t){
		lMaxTime = t;
	}
}
